/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ryopei.hatena;

import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;

/**
 *
 * @author ryohei
 */
public class SimpleEntryModel extends AbstractTableModel {

    private List<SimpleEntry> entries = new ArrayList<SimpleEntry>();
    private List<String> categories = new ArrayList<String>();

    public List<String> getCategories() {
        return categories;
    }

    public SimpleEntry getEntry(int index) {
        return entries.get(index);
    }

    public void add(SimpleEntry entry) {
        boolean isCategoryChanged = false;
        for (String category : entry.getCategories()) {
            if (!this.categories.contains(category)) {
                ;
                isCategoryChanged = true;
                this.categories.add(category);
            }
        }
        final int insertPos = entries.size();
        entries.add(entry);

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                fireTableRowsInserted(insertPos, insertPos);
            }
        });
        //列が増えた
        if (isCategoryChanged) {
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    fireTableStructureChanged();
                }
            });
        }
    }

    public int getRowCount() {
        return entries.size();
    }

    public int getColumnCount() {
        return 2 + categories.size();
    }

    @Override
    public String getColumnName(int column) {
        switch (column) {
            case 0:
                return "date";
            case 1:
                return "title";
            default:
                return categories.get(column - 2);

        }
    }

    public void clear() {
        this.categories.clear();
        this.entries.clear();
        fireTableDataChanged();
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            default:
                return Boolean.class;
        }
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        switch (columnIndex) {
            case 0:
                return entries.get(rowIndex).getDate();
            case 1:
                return entries.get(rowIndex).getTitle();
            default:
                return entries.get(rowIndex).getCategories().contains(categories.get(columnIndex - 2));
        }
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if (2 <= columnIndex && aValue instanceof Boolean) {
            String category = this.categories.get(columnIndex - 2);
            if ((Boolean) aValue) {
                entries.get(rowIndex).getCategories().add(category);
            } else {
                entries.get(rowIndex).getCategories().remove(category);
            }
        }
        //throw new UnsupportedOperationException();
    }

    public class RowHeaderModel extends AbstractTableModel {

        public RowHeaderModel() {
            SimpleEntryModel.this.addTableModelListener(new TableModelListener() {
                public void tableChanged(TableModelEvent e) {
                    fireTableChanged(new TableModelEvent(RowHeaderModel.this, e.getFirstRow()
                            , e.getLastRow(), e.getColumn()));
                }
            });
        }


        public int getRowCount() {
            return SimpleEntryModel.this.getRowCount();
        }

        public int getColumnCount() {
            return 2;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return SimpleEntryModel.this.getValueAt(rowIndex, columnIndex);
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            SimpleEntryModel.this.setValueAt(aValue, rowIndex, columnIndex);
        }

        @Override
        public String getColumnName(int column) {
            return SimpleEntryModel.this.getColumnName(column);
        }
    }

    private RowHeaderModel rowHeaderModel = new RowHeaderModel();

    public RowHeaderModel getRowHeaderModel() {
        return rowHeaderModel;
    }


    public class RowDataModel extends AbstractTableModel {


        public RowDataModel() {
            SimpleEntryModel.this.addTableModelListener(new TableModelListener() {
                public void tableChanged(TableModelEvent e) {
                    fireTableChanged(new TableModelEvent(RowDataModel.this, e.getFirstRow()
                            , e.getLastRow(), e.getColumn()-2));
                }
            });
        }
        public SimpleEntry getEntry(int column) {
            return SimpleEntryModel.this.getEntry(column);
        }

        public int getRowCount() {
            return SimpleEntryModel.this.getRowCount();
        }

        public int getColumnCount() {
            return SimpleEntryModel.this.getColumnCount() - 2;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return SimpleEntryModel.this.getValueAt(rowIndex, columnIndex + 2);
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return Boolean.class;
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            SimpleEntryModel.this.setValueAt(aValue, rowIndex, columnIndex + 2);
        }

        @Override
        public String getColumnName(int column) {
            return SimpleEntryModel.this.getColumnName(column + 2);
        }

    }

    private RowDataModel rowDataModel = new RowDataModel();

    public RowDataModel getRowDataModel() {
        return rowDataModel;
    }

}
